<?php
/**
 * Created by PhpStorm.
 * User: s.utkin
 * Date: 12.08.14
 * Time: 16:07
 */

namespace Messenger;

use Pinenut\Model2\Embedded\ReferenceContainer\One;
use Pinenut\Model2\Embedded\Reference;
use Users\Profile;
use Pinenut\Model2\Finder;

/**
 * Модель ссобщения
 *
 * @package Messеnger
 */
class Messages extends \Model
{
    /**
     * Группа, к которой относится сообщение
     *
     * @var Model2\Embedded\ReferenceContainer\One
     */
    public $group;

    /**
     * Автор сообщения
     *
     * @var \Pinenut\Model2\Embedded\ReferenceContainer\One
     */
    public $author;

    /**
     * Timestamp времени отправки сообщения
     *
     * @var int
     */
    public $sendTimestamp;

    /**
     * Timestamp времени прочтения сообщения получателем
     *
     * @var int
     */
    public $readTimestamp;

    /**
     * Текст сообщения
     *
     * @var string
     */
    public $text;

	/**
	 * Действие, вызываемое вместо вывода текста сообщения и возвращающее контент
	 * [
	 *   'name' => 'action.path',
	 *   'params' => ['param1' => 1, 'param1' => 'value 2' ... ]
	 * ]
	 * @var array
	 */
	public $action;

    /**
     * Поля модели
     *
     * @return array
     */
    static function fields()
    {
        return array_merge(
            parent::fields(),
            [
				'action' => static::MIXED,
                'author' => [
                    One::className(),
                    Reference::className(),
                    Profile::className(),
                ],
                'group' => [
                    One::className(),
                    Reference::className(),
                    Groups::className(),
                ],
                'sendTimestamp' => self::INT,
                'readTimestamp' => self::INT,
                'text' => self::STRING,
            ]
        );
    }

    /**
     * Возвращает сообщения группы
     *
     * @param $groupId - id группы
     * @param int $limit - лимит выбираемых сообщений
     * @param int $beforeTimestamp - лимит выбираемых сообщений
     * @return \Messenger\Messages[]
     */
    public function getGroupMessages($groupId, $limit = null, $beforeTimestamp = null)
    {
        $finder = self::find();
        $finder->where('group._ref', $groupId);

        if ($limit !== null) {
            $finder->limit((int)$limit);
        }

        if ($beforeTimestamp !== null) {
            $finder->where('sendTimestamp', $beforeTimestamp, Finder::OP_LT);
        }

        $finder->orderReverse('sendTimestamp');

        $messages = $finder->all();

        return array_reverse($messages);
    }

	public static function getLastReadTimestamp($groupId, $authorProfileId) {
		$finder = self::find();
		$finder->where('group._ref', $groupId);
		$finder->where('author._ref', $authorProfileId);
		$finder->where('readTimestamp', 0, Finder::OP_GT);
		$finder->orderReverse('sendTimestamp');
		$finder->limit(1);

		/** @var Messages $message */
		$message = $finder->one();

		return $message !== null ? $message->readTimestamp :  null;
	}

    /**
     * Возвращаем последнее сообщение пользователя в группе
     * --- старое:
	 * Возвращает true или false в зависимости от того, прочитано ли последнее
	 * сообщение пользователем
	 * 
	 * @return boolean
	 */
	public static function getLastMessage($groupId, $authorProfileId) {
		$finder = self::find();
		$finder->where('group._ref', $groupId);
		$finder->where('author._ref', $authorProfileId);
		$finder->orderReverse('sendTimestamp');
		$finder->limit(1);

		/** @var Messages $message */
        return $finder->one();
	}

    /**
     * Отрабатывает перед сохранением модели
     */
    public function beforeSave()
    {
        # Если сообщения еще нет в БД - устанавливаем время его отправки до 10^-4 секунды
        if ($this->isNew()) {
            $this->sendTimestamp = intval(microtime(true) * 10000.0);

            /*
             * Записываем в группу время последнего отправленного сообщения.
             * По полю lastMessageTime сортируются группы в списке пользователей.
             */
            /** @var Groups $groupModel */
            $groupModel = $this->group->getEntity();
            $groupModel->lastMessageTime = $this->sendTimestamp;
            $groupModel->save();
        }
    }

    /**
     * Возвращает true, если сообщение принадлежит пользователю с указанным id профиля
     *
     * @param $profileId - id профиля пользователя
     * @return bool
     */
    public function belongsToProfile($profileId)
    {
        return $this->author == $profileId;
    }

    /**
     * Возвращает true, если сообщение прочитано. Если установлено значение $value - меняется статус прочитанности
     *
     * @param bool|null $value
     * @return bool
     */
    public function isReaded($value = null)
    {
        if ($value !== null) {
            $this->readTimestamp = $value ? time() : null;
        }

        return $this->readTimestamp !== null;
    }

}